#include <functional>
#include <stdint.h>
#include <string>
#include <iostream>
#include <memory>
#include <unistd.h>
using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimeTask
{
public:
    TimeTask(uint64_t id, uint32_t timeout, const TaskFunc &cd) : _id(id), _timeout(timeout), _task_cd(cd), _is_running(true)
    {
    }
    ~TimeTask()
    {
       if(_is_running) _task_cd();
        _release_cd();
    }
    // 设置定时器释放函数
    void SetReleaseFunc(const ReleaseFunc &cd)
    {
        _release_cd = cd;
    }
    void Cancel() { _is_running = false; }    // 取消定时器任务
    uint32_t DelayTime() { return _timeout; } // 获取定时器延迟时间
private:
    uint64_t _id;            // 定时器任务对象id
    uint32_t _timeout;       // 定时器超时时间
    bool _is_running;        // 定时器任务是否被取消
    TaskFunc _task_cd;       // 定时器任务函数
    ReleaseFunc _release_cd; // 用于删除timeWheel中的定时器对象
};

class TimeWheel
{
public:
    TimeWheel() : _capacity(1024), _tick(0), _wheel(_capacity) {}
    ~TimeWheel() {}
    void TimerAdd(uint64_t id, uint32_t timeout, const TaskFunc &cd) // 添加定时器任务
    {
        Ptrtask pt(new TimeTask(id, timeout, cd));                        // 创建定时器对象
        pt->SetReleaseFunc(std::bind(&TimeWheel::RemoveTimer, this, id)); // 设置定时器释放函数
        int pos = (_tick + timeout) % _capacity;                          // 计算定时器位置
        _wheel[pos].push_back(pt);                                        // 保存定时器对象到指定位置的数组中
        _task_map[id] = pt;                                               // 保存定时器对象到任务映射表
    }
    void TimerDel(uint64_t id) // 删除定时器任务
    {
    }
    void TimerRefresh(uint64_t id) // 刷新、延迟定时任务
    {
        auto it = _task_map.find(id); // 找到定时器任务对象
        if (it == _task_map.end())
        {
            return;
        }
        Ptrtask pt = it->second.lock();        // lock()获取共享指针(weak_ptr)管理的对象对应的shared_ptr
        int delay = pt->DelayTime();           // 获取定时器延迟时间
        int pos = (_tick + delay) % _capacity; // 计算定时器位置
        _wheel[pos].push_back(pt);             // 保存定时器对象到指定位置的数组中
    }
    // 这个函数应该每秒被执行一次，相当于秒针向后走一步
    void RunTimerTask() // 执行定时器任务
    {
        _tick = (_tick + 1) % _capacity; // 时间轮指针向后走一步
        _wheel[_tick].clear();           // 清空指定位置的数组，就会把数组中保存的所有管理定时器对象的shared_ptr释放掉释放掉
    }

    void TimerCancel(uint64_t id) // 取消定时器任务
    {
        auto it = _task_map.find(id); // 找到定时器任务对象
        if (it == _task_map.end())
        {
            return;
        }
        Ptrtask pt = it->second.lock(); // lock()获取共享指针(weak_ptr)管理的对象对应的shared_ptr
        if(pt) pt->Cancel();
    }

private:
    void RemoveTimer(uint64_t id)
    {
        auto it = _task_map.find(id); // 找到定时器任务对象
        if (it != _task_map.end())
        {
            _task_map.erase(it); // 从任务映射表中删除定时器任务对象
        }
    }

private:
    using WeakTask = std::weak_ptr<TimeTask>;         // 弱引用
    using Ptrtask = std::shared_ptr<TimeTask>;        // 共享指针
    int _tick;                                        // 时间轮指针 ,当前指针走到哪里释放哪里,释放哪里，就相当于执行哪里任务
    int _capacity;                                    // 时间轮容量---最大延迟时间
    std::vector<std::vector<Ptrtask>> _wheel;         // 时间轮
    std::unordered_map<uint64_t, WeakTask> _task_map; // 任务id与任务对象映射表
};

class Timer
{
public:
    Timer()
    {
        std::cout << "Timer" << std::endl;
    }
    ~Timer()
    {
        std::cout << "~Timer" << std::endl;
    }
};

void test(Timer *timer)
{
    delete timer;
}

int main()
{
    Timer *t = new Timer();
    TimeWheel tw;
    tw.TimerAdd(1, 5, std::bind(test, t));
    for (int i = 0; i < 5; i++)
    {
        sleep(1);

        tw.TimerRefresh(1);
        tw.RunTimerTask(); // 执行定时器任务
        std::cout << "重新刷新定时事件，在5秒好执行" << std::endl;
    }
    tw.TimerCancel(1); // 取消定时器任务
    while (1)
    {
        sleep(1);
        std::cout << "执行定时器任务" << std::endl;
        tw.RunTimerTask(); // 执行定时器任务
    }

    return 0;
}